//: Playground - noun: a place where people can play

import UIKit

// 回顾 可选值那里

struct Order {
    let orderNumber: Int
    let person: Person?
}

struct Person {
    let name: String
    let address: Address?
}

struct Address {
    let streetName: String
    let city: String
    let state: String?
}

// 获取地址

enum LookupError: ErrorType {
    case PersonNotFound
    case AddressNotFound
    case StateNotFount
}

enum OrderResult {
    case Success(String)
    case Error(LookupError)
}

func orderInfo(order: Order) -> OrderResult {
    guard let myPerson = order.person else {
        return .Error(.PersonNotFound)
    }
    guard let myAddress = myPerson.address else {
        return .Error(.AddressNotFound)
    }
    guard let myState = myAddress.state else {
        return .Error(.StateNotFount)
    }
    return .Success(myState)
}



// 实例 Order

let orderNoPerson = Order(orderNumber: 1, person: nil)
let orderNoAddress = Order(orderNumber: 2, person: Person(name: "zZ爱吃菜", address: nil))
let orderNoState = Order(orderNumber: 3, person: Person(name: "zZ爱吃菜", address: Address(streetName: "Fenjiang", city: "Foshan", state: nil)))
let orderFull = Order(orderNumber: 4, person: Person(name: "zZ爱吃菜", address: Address(streetName: "Fenjiang", city: "Foshan", state: "China")))

orderInfo(orderNoPerson)
orderInfo(orderNoAddress)
orderInfo(orderNoState)
orderInfo(orderFull)


func getOrderInfoResult(result: OrderResult) -> String {
    switch result {
    case let .Success(state):
        return "获取地址：\(state)"
    case let .Error(error):
        return "错误原因：\(error)"
    }
}

getOrderInfoResult(orderInfo(orderNoPerson))

getOrderInfoResult(orderInfo(orderNoAddress))

getOrderInfoResult(orderInfo(orderNoState))

getOrderInfoResult(orderInfo(orderFull))

// 这样可以制作一个通用型的结果校验枚举，即返回正确时的类型可以自定义，String Int 等等
enum Result<T>{
    case Success(T)
    case Error(ErrorType)
}


//: ### Swift 中的错误处理

// Swift 内建错误处理机制的局限性再与，他必须接住函数的返回类型来触发

// 重写 orderInfo 函数，重构带有错误处理机制的函数

func orderInfo1(order: Order) throws -> String {
    guard let myPerson = order.person else {
        throw LookupError.PersonNotFound
    }
    guard let myAddress = myPerson.address else {
        throw LookupError.AddressNotFound
    }
    guard let myState = myAddress.state else {
        throw LookupError.StateNotFount
    }
    return myState
}

// 通过 do ... catch 代码块执行带错误处理机制的函数：

do {
    let state = try orderInfo1(orderNoPerson)
    print("地址是：\(state)")
} catch {
    print("错误原因：\(error)")
}



//: #### 聊聊可选型

// 类似于讲一个 可选型解包，要么获取真值，要么给他一个同类型的默认值

func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T {
    switch result {
    case let .Success(value):
        return value
    case let .Error(error):
        return handleError(error)
    }
}


















